﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Web.Script.Serialization;
using System.Reflection;
using System.Collections;

namespace NetFramework
{
    public class SerializeHelper
    {
        public static void SerializeToNameValueCollection<T>(NameValueCollection nameValueCollection, T obj) where T : class
        {
            Type type = typeof(T);

            var fields = type.GetFields();
            foreach (var field in fields)
            {
                string key = field.Name;
                var value = field.GetValue(obj);

                if (value != null)
                    nameValueCollection.Add(key, value.ToString());
            }
        }

        public static Dictionary<Type, PropertyInfo[]> instanceProperties = new Dictionary<Type, PropertyInfo[]>();
        private static readonly object syncObj = new object();

        public static T DeserializeFromNameValueCollection<T>(NameValueCollection nameValueCollection) where T : class
        {
            Type type = typeof(T);
            PropertyInfo[] propertyInfos;

            if (!instanceProperties.TryGetValue(type, out propertyInfos))
            {
                lock (syncObj)
                {
                    if (!instanceProperties.TryGetValue(type, out propertyInfos))
                    {
                        propertyInfos = type.GetProperties();
                        instanceProperties.Add(type, propertyInfos);
                    }
                }
            }

            
            object obj = Activator.CreateInstance(type);
            try
            {
                if (propertyInfos != null && propertyInfos.Length > 0)
                {
                    foreach (PropertyInfo p in propertyInfos)
                    {
                        string value = nameValueCollection[p.Name];
                        if (!string.IsNullOrEmpty(value) && p.CanWrite)
                        {
                            if (p.PropertyType.BaseType.Equals(typeof(Enum)))
                            {
                                p.SetValue(obj, Enum.Parse(p.PropertyType, value.ToString()), null);
                            }
                            else
                            {
                                p.SetValue(obj, Convert.ChangeType(value, p.PropertyType), null);
                            }
                        }
                    }
                }
            }
            catch
            {
                return null;
            }

            return obj as T;
        }
    }
}
